package com.moogene.android.engine.font;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;

import com.moogene.android.InfoMediator;
import com.moogene.android.R;

public class Latin {
	public final static int FONT1 = 0;
	public final static int FONT2 = 1;
	final private static int NUM_LETTER_FONTS = 2;
	final private static int[] LETTER_FONTS_RES_ID = { R.drawable.font1,
			R.drawable.font2 };
	final private static int[] LETTER_FONTS_BIN_RES_ID = { R.raw.font1,
			R.raw.font2 };

	final private static int LETTER_LOWERCASE = 0;
	final private static int LETTER_UPPERCASE = 26;
	final private static int LETTER_NUMBER = 52;
	final private static int LETTER_COMMA = 62;
	final private static int LETTER_STOP = 63;
	final private static int LETTER_QUESTION = 64;
	final private static int LETTER_SIGN = 65;
	final private static int LETTER_AT = 66;
	final private static int LETTER_COLON = 67;
	final private static int LETTER_SLASH = 68;
	final private static int LETTER_COPYRIGHT = 69;
	final private static int LETTER_BLANK = 70;

	final private static int NUM_LETTER = 71;

	final private static char LETTER_NEWLINE = '\n';
	final private static char LETTER_NEWLINE_CENTER = '\t';

	private int letterGapX = 0;
	private int letterGapY = 25;

	private Bitmap[] textImg;
	private Rect[][] letterSourceRect;
	private int[] textMaxHeight;

	private boolean sIsCenter;

	private Paint sTextPaint = null;

	private static Latin sLatin;

	private Latin() {
	}

	public static Latin getInstance() {
		if (sLatin == null) {
			sLatin = new Latin();
			sLatin.initGfxText();
		}
		return sLatin;
	}

	void initGfxText() {
		Resources resource = InfoMediator.getResHandler();
		letterSourceRect = new Rect[NUM_LETTER_FONTS][NUM_LETTER];
		textImg = new Bitmap[NUM_LETTER_FONTS];
		textMaxHeight = new int[NUM_LETTER_FONTS];
		int left, top, right, bottom;
		for (int i = 0; i < NUM_LETTER_FONTS; i++) {
			textImg[i] = InfoMediator.getBitmap(LETTER_FONTS_RES_ID[i]);
			int maxHeight = 0;
			// sLetterSourceRect = new Rect[NUM_LETTER];
			InputStream is = resource
					.openRawResource(LETTER_FONTS_BIN_RES_ID[i]);
			DataInputStream dis = new DataInputStream(is);
			try {
				for (int j = 0; j < NUM_LETTER; j++) {
					left = dis.readInt();
					top = dis.readInt();
					right = dis.readInt();
					bottom = dis.readInt();
					letterSourceRect[i][j] = new Rect(left, top, right, bottom);
					if(bottom - top > maxHeight){
						maxHeight = bottom - top;
					}
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			textMaxHeight[i] = maxHeight;
		}
	}

	private static int getLetterNo(char letter) {
		int letterNo = ' ';
		if (letter >= 'A' && letter <= 'Z') {
			letterNo = letter - 'A' + LETTER_UPPERCASE;
		} else if (letter >= 'a' && letter <= 'z') {
			letterNo = letter - 'a' + LETTER_LOWERCASE;
		} else if (letter >= '0' && letter <= '9') {
			letterNo = letter - '0' + LETTER_NUMBER;
		} else if (letter == ',') {
			letterNo = LETTER_COMMA;
		} else if (letter == '.') {
			letterNo = LETTER_STOP;
		} else if (letter == '?') {
			letterNo = LETTER_QUESTION;
		} else if (letter == '!') {
			letterNo = LETTER_SIGN;
		} else if (letter == '@') {
			letterNo = LETTER_AT;
		} else if (letter == ':') {
			letterNo = LETTER_COLON;
		} else if (letter == '/') {
			letterNo = LETTER_SLASH;
		} else if (letter == (char)0xA9) {
			letterNo = LETTER_COPYRIGHT;
		} else if (letter == ' ') {
			letterNo = LETTER_BLANK;
		} else {
			throw new IllegalArgumentException("Unsupported letter: " + letter);
		}
		return letterNo;
	}

	public int getTextWidth(String text, int fontId) {
		int width = 0;
		char letter;
		int letterNo;
		int len = text.length();
		for (int i = 0; i < len; i++) {
			letter = text.charAt(i);
			letterNo = getLetterNo(letter);
			// System.out.println("getTextWidth; letterNo: " + letterNo);
			width += letterSourceRect[fontId][letterNo].right
					- letterSourceRect[fontId][letterNo].left + letterGapX;
		}
		return width;
	}

	public int getMaxHeight(int fontId){
		return textMaxHeight[fontId];
	}

	public int drawText(Canvas canvas, int fontId, String text, Rect bounds, int gapX, int gapY) {
		int gapXp = letterGapX;
		int gapYp = letterGapY;
		this.letterGapX = gapX;
		this.letterGapY = gapY;
		int numLine = drawText(canvas, fontId, text, bounds);
		letterGapX = gapXp;
		letterGapY = gapYp;
		return numLine;
	}

	public int drawText(Canvas canvas, int fontId, String text, Rect bounds, Paint p) {
		sTextPaint = p;
		int tmp = drawText(canvas, fontId, text, bounds);
		sTextPaint = null;
		return tmp;
	}

	/**
	 * @param canvas
	 * @param fontId
	 * @param text
	 * @param x
	 * @param y
	 * @param w
	 * @param h
	 * @return the number of lines
	 */
	public int drawText(Canvas canvas, int fontId, String text, Rect bounds) {
		int x = bounds.left;
		int y = bounds.top;
		int w = bounds.width();
		int h = bounds.height();
		int cursorX = x;
		int cursorY = y;
		int len = text.length();
		char letter;
		int letterNo;
		int indexBegin = 0;
		int indexEnd = 0;
		int indexlastBlank = 0;
		sIsCenter = false;
		Rect dst;
		int width;
		int height;
		boolean shouldEndLine;
		int subStrWidth = 0;
		int numline = 0;
		// canvas.clipRect(x, y, x + w, y + h);
		do {
			shouldEndLine = false;
			do {
				indexlastBlank = indexEnd;
				indexEnd = text.indexOf(' ', indexEnd + 1);
				if (indexEnd == -1) {
					indexEnd = len;
				} else if (text.charAt(indexEnd - 1) == LETTER_NEWLINE) {
					shouldEndLine = true;
					indexEnd--;
					// subStr = text.substring(indexBegin, indexEnd - 1);
					sIsCenter = false;
				} else if (text.charAt(indexEnd - 1) == LETTER_NEWLINE_CENTER) {
					shouldEndLine = true;
					indexEnd--;
					sIsCenter = true;
				}
				// String substr = text.substring(indexBegin, indexEnd);
				subStrWidth = getTextWidth(
						text.substring(indexBegin, indexEnd), fontId);
				if (subStrWidth > w) {
					// indexEnd = indexlastBlank;
					if (indexlastBlank + 1 != indexBegin) {
						shouldEndLine = false;
						indexEnd = indexlastBlank;
						// indexEnd = text.indexOf(' ', indexBegin + 1);
						// throw new IllegalArgumentException("Too long word: "
						// + text.substring(indexBegin, text.indexOf(' ',
						// indexBegin)));
					}
					break;
				}
				if (indexEnd == len || shouldEndLine) {
					break;
				}
			} while (true);
			if (sIsCenter) {
				cursorX += ((w - subStrWidth) >> 1);
			}
			for (int i = indexBegin; i < indexEnd; i++) {
				letter = text.charAt(i);
				letterNo = getLetterNo(letter);

				width = letterSourceRect[fontId][letterNo].right
						- letterSourceRect[fontId][letterNo].left;
				height = letterSourceRect[fontId][letterNo].bottom
						- letterSourceRect[fontId][letterNo].top;
				if (letterNo != LETTER_BLANK) {
					dst = new Rect(cursorX, cursorY, cursorX + width, cursorY
							+ height);
					canvas.drawBitmap(textImg[fontId],
							letterSourceRect[fontId][letterNo], dst,
							sTextPaint);
				}
				cursorX += width + letterGapX;
			}
			if (shouldEndLine) {
				indexEnd++;
			}
			indexBegin = indexEnd + 1;

			cursorX = x;
			cursorY += letterGapY;
			numline++;
		} while (indexEnd != len);
		return numline;
	}
}
